package com.example.idlefish.Message
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Base64
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.room.Room
import com.example.idlefish.GoodsInfo.ActivityContract.GoodBuySuccessContract
import com.example.idlefish.GoodsInfo.GoodBuySuccessActivity
import com.example.idlefish.GoodsInfo.parseGson.paraseBuyInfo
import com.example.idlefish.GoodsInfo.pojo.GoodEase
import com.example.idlefish.PublicModule.ApplicationConst
import com.example.idlefish.PublicModule.ApplicationConst.server_ip
import com.example.idlefish.PublicModule.CommonUtil
import com.example.idlefish.PublicModule.IdleFishDatabase
import com.example.idlefish.PublicModule.NetworkSettings
import com.example.idlefish.PublicModule.UserConst
import com.example.idlefish.R
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.gson.Gson
import com.google.gson.JsonObject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONArray
import org.json.JSONObject
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.InputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class MessageChatActivity : AppCompatActivity() {
    private val client = OkHttpClient()

    private  lateinit var db: IdleFishDatabase
    private  lateinit var messageChatDao: MessageChatDAO


    var messageData : MessagePreviewData = MessagePreviewData(0, 0, "", "", "", "", "", "", "", 0)
    var oldMessageList = mutableListOf<MessageChatData>()
    private lateinit var recyclerView: RecyclerView

    private lateinit var goodInfo: GoodEase
    private val goodPic1 = ApplicationConst.goodPic1
    private lateinit var bottomSheetBuyDialog : BottomSheetDialog
    private lateinit var bottomView:View
    private var Address:String = ""
    private var buylauncher = registerForActivityResult(GoodBuySuccessContract()){
        result->
    }
    private lateinit var loadingLayout: LinearLayout
    companion object {
        private const val REQUEST_CODE_IMAGE_PICK = 1001
        private const val REQUEST_CODE_IMAGE_SHOOT = 1002
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.message_chat)

        val rootLayout = findViewById<LinearLayout>(R.id.root_layout1)
        val inflater = LayoutInflater.from(this)
        loadingLayout = inflater.inflate(R.layout.load_layout, rootLayout, false) as LinearLayout
        rootLayout.addView(loadingLayout)


        db = IdleFishDatabase.getDatabase(applicationContext)
        messageChatDao = db.messageChatDao()
        // goodInfo = CommonUtil.getSerializable(intent , "goodInfo", GoodEase::class.java)
        // Log.i("传入的商品简单信息", goodInfo.toString())

        messageData = intent.getSerializableExtra("messageInfo", MessagePreviewData::class.java)!!
        goodInfo = intent.getSerializableExtra("goodInfo", GoodEase::class.java)!!
        recyclerView = findViewById<RecyclerView>(R.id.recyclerView_message_chat)
        recyclerView.layoutManager = LinearLayoutManager(this)
        getMessageList()

        //购买上拉窗体
        bottomSheetBuyDialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
        bottomView = LayoutInflater.from(this).inflate(R.layout.buy_bottom_sheet_layout, null, false)


        val messageChatReceiverName = findViewById<TextView>(R.id.textView_message_main_chat_username)
        messageChatReceiverName.setText(messageData.receiverName)

        val goodPrice = findViewById<TextView>(R.id.message_chat_goodprice)
        if (goodInfo.goodPrice != null) {
            goodPrice.setText("￥" + goodInfo.goodPrice.toString())
        }


        val goodPhoto = findViewById<ImageView>(R.id.imageView_message_preview_goodPicture)
        goodPhoto.setImageResource(R.drawable.default_image)
        if (ApplicationConst.goodPic1 != null) {
            goodPhoto.setImageBitmap(goodPic1)
        }


        val buyButton = findViewById<Button>(R.id.buy)
        val editTextMessageChat = findViewById<EditText>(R.id.editText_message_chat)
        val buttonMessageMore = findViewById<Button>(R.id.button_message_main_chat_messageMore)
        val buttonMessageSend = findViewById<Button>(R.id.button_message_main_chat_send)
        val buttonReturn = findViewById<Button>(R.id.button_message_main_chat_return)


        editTextMessageChat.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (s.isNullOrEmpty()) {
                    buttonMessageMore.visibility = View.VISIBLE
                    buttonMessageSend.visibility = View.GONE
                } else {
                    buttonMessageMore.visibility = View.GONE
                    buttonMessageSend.visibility = View.VISIBLE
                }
            }

            override fun afterTextChanged(s: Editable?) {}

        })

        editTextMessageChat.setOnClickListener {
            editTextMessageChat.postDelayed({
                recyclerView.scrollToPosition((recyclerView.adapter as MessageChatAdapter).itemCount - 1)
            }, 100)
        }

        buttonMessageSend.setOnClickListener {
            //检验sender和receiver是否反了
            var receiverID : Int
            if (messageData.senderID == UserConst.id.toInt())
            {
                receiverID = messageData.receiverID
            }
            else
            {
                receiverID = messageData.senderID
            }

            val message = MessageChatData(
                senderID = UserConst.id.toInt(),
                receiverID = receiverID,
                messageID = 0,
                messageContent = editTextMessageChat.text.toString(),
                messageContentPhoto = "",
                messageContentVoice = "",
                messageTime = getCurrentTime()
            )
            sendPostRequest(message)
            editTextMessageChat.text.clear()
        }

        buttonReturn.setOnClickListener {
            finish()
        }
        buyButton.setOnClickListener {
            bottomSheetBuyDialog.setContentView(bottomView)
            val buynow = bottomView.findViewById<Button>(R.id.buynow)
            val imageView_message_preview_goodPicture = bottomView.findViewById<ImageView>(R.id.imageView_message_preview_goodPicture)
            val pooPrice = bottomView.findViewById<TextView>(R.id.pooPrice1)
            val postPrice = bottomView.findViewById<TextView>(R.id.postPrice)
            val goodTittle = bottomView.findViewById<TextView>(R.id.goodTittle)
            goodTittle.text = goodInfo.goodName
            postPrice.text = "¥" + goodInfo.postPrice.toString()
            pooPrice.text = "¥"+ goodInfo.goodPrice.toString()
            bottomSheetBuyDialog.show()

            imageView_message_preview_goodPicture.setImageBitmap(goodPic1)
            buynow.setOnClickListener {
                val address = bottomView.findViewById<EditText>(R.id.buyAddress).text.toString()
                Address = address
                if(address.length > 5) {
                    bottomSheetBuyDialog.dismiss()
                    loadingLayout.visibility = View.VISIBLE
                    confirmOnNet()
                }
                else
                {
                    Toast.makeText(applicationContext, "地址信息太简短了，请详细填写", Toast.LENGTH_LONG)
                }
            }
        }


        buttonMessageMore.setOnClickListener {
            showBottomSheetDialog()
        }


    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE_IMAGE_PICK && resultCode == RESULT_OK) {
            val selectedImageUri = data?.data
            if (selectedImageUri != null) {
                val base64Image = getBase64FromUri(selectedImageUri)
                if (base64Image != null) {
                    val message = MessageChatData(
                        senderID = UserConst.id.toInt(),
                        receiverID = messageData.receiverID,
                        messageID = 0,
                        messageContent = "",
                        messageContentPhoto = "",
                        messageContentVoice = "",
                        messageTime = getCurrentTime()
                    )
                    sendPostRequest(message, base64Image)
                }
            }
        }
    }

    private fun openImageChooser() {
        val intent = Intent(Intent.ACTION_PICK)
        intent.type = "image/*"
        startActivityForResult(intent, REQUEST_CODE_IMAGE_PICK)
    }

    private fun showBottomSheetDialog() {
        val bottomSheetDialog = BottomSheetDialog(this)
        val bottomSheetView = LayoutInflater.from(this).inflate(R.layout.message_chat_bottom_sheet_dialog, null)
        bottomSheetDialog.setContentView(bottomSheetView)

        bottomSheetView.findViewById<Button>(R.id.button_message_chat_photoChoose).setOnClickListener {
            // Handle option 1 click
            openImageChooser()
            bottomSheetDialog.dismiss()
        }

        bottomSheetView.findViewById<Button>(R.id.button_message_chat_photoShoot).setOnClickListener {
            // Handle option 2 click
            bottomSheetDialog.dismiss()
        }

        bottomSheetDialog.show()
    }



    private fun getBase64FromUri(uri: Uri): String? {
        val inputStream: InputStream? = contentResolver.openInputStream(uri)
        val bitmap = BitmapFactory.decodeStream(inputStream)
        val byteArrayOutputStream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream)
        val byteArray = byteArrayOutputStream.toByteArray()
        return Base64.encodeToString(byteArray, Base64.DEFAULT)
    }


    private fun getCurrentTime(): String {
        val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
        return dateFormat.format(Date())
    }

    private fun sendPostRequest(message: MessageChatData, image : String? = null) {
        val gson = Gson()
        val jsonMessage = gson.toJson(message)
        val requestBody = jsonMessage.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())

        val request = Request.Builder()
            .url(NetworkSettings.HTTP + "/message/messagePost")
            .post(requestBody)
            .build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                e.printStackTrace()
            }

            override fun onResponse(call: Call, response: Response) {
                if (response.isSuccessful) {
                    println("Message updated successfully")
                    getMessageList()
                } else {
                    println("Failed to update message")
                }
            }
        })
    }

    private fun getMessageList() {
        // Load chat data from local database first
        CoroutineScope(Dispatchers.IO).launch {
            val localMessageList = messageChatDao.getMessagesByID(messageData.senderID, messageData.receiverID)
            if (oldMessageList.isNullOrEmpty())
            {
                oldMessageList = localMessageList.toMutableList()
                withContext(Dispatchers.Main) {
                    if (recyclerView.adapter == null) {
                        recyclerView.adapter = MessageChatAdapter(localMessageList, messageData)
                    } else {
                        (recyclerView.adapter as MessageChatAdapter).updateMessages(localMessageList)
                    }
                    recyclerView.scrollToPosition((recyclerView.adapter as MessageChatAdapter).itemCount - 1)
                }
            }

            // Make network request to fetch latest chat data
            val gson = Gson()
            val url = NetworkSettings.HTTP + "/message/messageGet?senderID=${messageData.senderID}&receiverID=${messageData.receiverID}"
            val request = Request.Builder()
                .url(url)
                .build()

            client.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    e.printStackTrace()
                }

                override fun onResponse(call: Call, response: Response) {
                    if (response.isSuccessful) {
                        val body = response.body?.string()
                        val messageList = gson.fromJson(body, Array<MessageChatData>::class.java).toMutableList()
                        val localMessageIDs = localMessageList.map { it.messageID }.toSet()

                        for (message in messageList) {
                            if (!localMessageIDs.contains(message.messageID)) {
                                messageChatDao.insertMessage(message)
                            }
                        }
                        val newLocalMessageList = messageChatDao.getMessagesByID(messageData.senderID, messageData.receiverID)
                        val newMessages = newLocalMessageList.filter { newMessage ->
                            oldMessageList.none { oldMessage -> oldMessage.messageID == newMessage.messageID }
                        }
                        oldMessageList = newLocalMessageList.toMutableList()
                        runOnUiThread {
                            if (recyclerView.adapter == null) {
                                recyclerView.adapter = MessageChatAdapter(newLocalMessageList, messageData)
                            } else {
                                (recyclerView.adapter as MessageChatAdapter).updateMessages(newMessages)
                            }
                            recyclerView.scrollToPosition((recyclerView.adapter as MessageChatAdapter).itemCount - 1)
                        }
                    } else {
                        println("Failed to get messages")
                    }
                }
            })
        }
    }

    fun confirmOnNet(){
        val client =  OkHttpClient()
        val jsp = "http://${server_ip}:8080/BuyGood"
        //需要传递 goodId buyerId Address
        val requestBodyJson = JSONObject().apply {
            put("goodId", goodInfo.goodId)
            put("buyerId", UserConst.id)
            put("address", Address)
        }.toString()
        Log.d("BUYnetRequest", requestBodyJson)
        val requestBody = RequestBody.create("application/json;charset=utf-8".toMediaType(), requestBodyJson)
        val request = Request.Builder()
            .url(jsp)
            .post(requestBody)
            .build()

        client.newCall(request).enqueue(object : Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.i("collect", "购买请求失败")
                loadingLayout.visibility = View.GONE
            }

            override fun onResponse(call: Call, response: Response) {
                Log.i("collect", "购买请求成功返回")
                val info = response.body?.string().toString()
                runOnUiThread {
                    val result = paraseBuyInfo.paraseBuyInfo(info)
                    if(result.success == 1)
                    {
                        result.price =  goodInfo.goodPrice
                        result.postPrice = goodInfo.postPrice
                        result.goodName = goodInfo.goodName
                        buylauncher.launch(result)
                        Toast.makeText(applicationContext, "购买成功", Toast.LENGTH_SHORT).show()
                    }
                    else
                    {
                        Toast.makeText(applicationContext, "您的购买请求失败了，请重试", Toast.LENGTH_LONG).show()
                    }
                    loadingLayout.visibility = View.GONE
                }
            }
        })
    }

}